#ifndef _BUF_TOKEN
#define _BUF_TOKEN

#include <queue>
#include <string>
#include "Buffer.h"

namespace mylib {
	namespace buf_token_loc {
		const int FROM_FILE = false;
		const int FROM_BACK = true;
	}
	template<class C, class T> class Buf_token {
	public :
		Buf_token(mylib::Buffer &in) : tokens(in){ from = buf_token_loc::FROM_FILE; }
		~Buf_token() {
			while(!back.empty()) {
				C *t = back.front();
				delete t;
				back.pop();
			}
		}
		class Out_of_mem {};
		T get() {
			if( from == buf_token_loc::FROM_BACK ) { // from file
				delete back.front();
				back.pop();		// delete it
			}
			if( back.empty() ) {
				from = buf_token_loc::FROM_FILE;	// get from file
				return tokens.get();
			} else {
				from = buf_token_loc::FROM_BACK;
				return back.front()->type();
			}
		}
		T type(){ if( from == buf_token_loc::FROM_FILE ) return tokens.type(); else return back.front()->type(); }
		size_t len() { if( from == buf_token_loc::FROM_FILE ) return tokens.len(); else return back.front()->len(); }
		const std::string &token() { 
			if( from == buf_token_loc::FROM_FILE) return tokens.token(); 
			else return back.front()->token(); 
		}
		Buf_token &push(const std::string &str, T t) {
			try {
				C *temp = new C(str, t);
				back.push(temp);
			} catch(...) {
				throw Out_of_mem();
			}
			return *this;
		}
	private :
		C tokens;
		std::queue<C *> back;
		bool from;
	};
}
#endif
